# 1. 函数式视图  Function Based View
# 2. 类视图  Classed Based View
# 3. 通用类视图  Generic Classed Based View
# 4. 视图集  ViewSets
from django.db.models.signals import post_save  # 信号
from django.dispatch import receiver  # receiver装饰
from django.contrib.auth.models import User  # 或者是下
from django.conf import settings

from rest_framework.decorators import api_view, authentication_classes, permission_classes  # 函数式api视图
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from rest_framework import generics
from rest_framework import viewsets

from rest_framework.authtoken.models import Token  # token表导入

from rest_framework.authentication import BasicAuthentication, SessionAuthentication, TokenAuthentication

from rest_framework.permissions import IsAuthenticated

from .permissions import IsOwnerReadonly
from .models import Course
from .serializers import CourseSerializer

# @receiver(post_save, sender=User)
@receiver(post_save, sender=settings.AUTH_USER_MODEL)  # django的信号机制
def generate_token(sender, instance=None, created=False, **kwargs):
    """
    生成token
    :param sender:
    :param instance:
    :param created:
    :param kwargs:
    :return:
    """
    if created:
        Token.objects.create(user=instance)

# 1. FBV
@api_view(['GET', 'POST'])
@authentication_classes((BasicAuthentication, SessionAuthentication, TokenAuthentication))  # 给方法加验证类型
@permission_classes((IsAuthenticated, ))
def course_list(request):
    """
    获取所有课程; 新增一个课程
    :param request:
    :return:
    """
    if request.method == 'GET':
        s = CourseSerializer(Course.objects.all(), many=True)
        return Response(s.data, status.HTTP_200_OK)

    if request.method == 'POST':
        s = CourseSerializer(data=request.data)  # 部分更新用partial=True属性
        if s.is_valid():
            s.save(teacher=request.user)
            return Response(s.data, status.HTTP_201_CREATED)
        return Response(s.errors, status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'PUT', 'DELETE'])
def course_detail(request, pk):
    """
    获取所有匹配详情; 更新信息; 删除信息
    :param request:
    :param pk:
    :return:
    """
    try:
        course = Course.objects.get(pk=pk)  # get/first是一条信息，all,filter是多条信息
    except Course.DoesNotExist:
        return Response(data={"msg": "未找到课程信息"}, status=status.HTTP_404_NOT_FOUND)
    else:
        if request.method == 'GET':
            s = CourseSerializer(instance=course)
            return Response(data=s.data, status=status.HTTP_200_OK)
        elif request.method == 'PUT':
            s = CourseSerializer(instance=course, data=request.data)
            if s.is_valid():
                s.save()
                return Response(data=s.data, status=status.HTTP_200_OK)
        elif request.method == 'DELETE':
            course.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)


# 2. CBV
class CourseList(APIView):

    authentication_classes = (BasicAuthentication, SessionAuthentication, TokenAuthentication)  # 类视图添加内置authentication_classes
    permission_classes = (IsAuthenticated, )

    def get(self, request):
        """
        :param request:
        :return:
        """
        print(self.request.user, self.request.auth)
        print(type(self.request.user), type(self.request.auth))  # <class 'django.contrib.auth.models.User'> <class 'rest_framework.authtoken.models.Token'>

        queryset = Course.objects.all()
        s = CourseSerializer(instance=queryset, many=True)
        return Response(s.data, status.HTTP_200_OK)

    def post(self, request):
        """
        :param request:
        :return:
        """
        s = CourseSerializer(data=request.data)
        if s.is_valid():
            s.save(teacher=request.user)
            # print(type(request.data), type(s.data))  # <class 'dict'> <class 'rest_framework.utils.serializer_helpers.ReturnDict'>
            return Response(s.data, status.HTTP_201_CREATED)
        return Response(s.errors, status.HTTP_400_BAD_REQUEST)

class CourseDetail(APIView):
    @staticmethod  # 供调用
    def get_object(pk):
        """
        :param pk:
        :return:
        """
        try:
            return Course.objects.get(pk=pk)
        except Course.DoesNotExist:
            return

    def get(self, request, pk):
        """
        :param request:
        :param pk:
        :return:
        """
        obj = self.get_object(pk=pk)
        if not obj:
            return Response(data={"msg": "未找到课程信息"}, status=status.HTTP_404_NOT_FOUND)
        s = CourseSerializer(instance=obj)
        return Response(s.data, status=status.HTTP_200_OK)

    def put(self, request, pk):
        """
        :param request:
        :param pk:
        :return:
        """
        obj = self.get_object(pk=pk)
        if not obj:
            return Response(data={"msg": "未找到课程信息"}, status=status.HTTP_404_NOT_FOUND)
        s = CourseSerializer(instance=obj, data=request.data)
        if s.is_valid():
            s.save()
            return Response(s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        """
        :param request:
        :param pk:
        :return:
        """
        obj = self.get_object(pk=pk)
        if not obj:
            return Response(data={"msg": "未找到课程信息"}, status=status.HTTP_404_NOT_FOUND)
        obj.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

# 3. GCBV
class GCourseList(generics.ListCreateAPIView):  # generics里有很多定义好的APIView
    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    permission_classes = (IsAuthenticated, IsOwnerReadonly, )
    def perform_create(self, serializer):
        serializer.save(teacher=self.request.user)

# from rest_framework import mixins
# from rest_framework.generics import GenericAPIView
# class GCourseDetail(mixins.RetrieveModelMixin,
#                                    mixins.UpdateModelMixin,
#                                    mixins.DestroyModelMixin,
#                                    GenericAPIView):
class GCourseDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    permission_classes = (IsAuthenticated, IsOwnerReadonly,)

# 4. ViewSets
class CourseViewSet(viewsets.ModelViewSet):
    queryset = Course.objects.all()
    serializer_class = CourseSerializer

    def perform_create(self, serializer):
        serializer.save(teacher=self.request.user)



